package com.atguigu.gmall.service.impl;

import com.atguigu.gmall.common.util.DateUtil;
import com.atguigu.gmall.service.CartService;
import com.atguigu.gmall.cart.model.CartInfo;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.product.client.ProductFeignClient;
import com.atguigu.gmall.product.model.SkuInfo;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author: atguigu
 * @create: 2023-01-11 10:47
 */
@Service
public class CartServiceImpl implements CartService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private ProductFeignClient productFeignClient;

    /**
     * 用户将商品加入到购物车-存储到Redis
     *
     * @param userId
     * @param skuId  商品SKUID
     * @param skuNum 商品加购的数量
     * @return
     */
    @Override
    public void addToCart(String userId, Long skuId, Integer skuNum) {
        //1.构建购物车结构 redisKey 包含登录用户ID或者临时用户ID
        //1.1 登录用户ID作为 形式：user:1:cart
        String redisKey = getCartKey(userId);
        //1.2 创建hash操作对象 - 决定操作数据都是传入用户购物车数据
        //BoundHashOperations<redisKey类型，hashKey类型，hashValue类型>
        BoundHashOperations<String, String, CartInfo> hashOps = redisTemplate.boundHashOps(redisKey);

        //2.参数中skuID作为hashKey 标识商品  注意：hashKey类型必须是字符串
        String hashKey = skuId.toString();

        //3.构建hashVal 将商品信息+数量
        //3.1 远程调用商品微服务获取商品信息
        SkuInfo skuInfo = productFeignClient.getSkuInfo(skuId);
        if (skuInfo != null) {
            CartInfo cartInfo = null;
            if (hashOps.hasKey(skuId.toString())) {
                cartInfo = hashOps.get(skuId.toString());
                cartInfo.setSkuNum(cartInfo.getSkuNum() + skuNum);
            } else {
                //3.2 封装商品购物车对象
                cartInfo = new CartInfo();
                cartInfo.setSkuId(skuId);
                cartInfo.setImgUrl(skuInfo.getSkuDefaultImg());
                cartInfo.setSkuName(skuInfo.getSkuName());
                cartInfo.setSkuNum(skuNum);
                cartInfo.setIsChecked(1);
                cartInfo.setCreateTime(new Date());
                cartInfo.setUpdateTime(new Date());
                cartInfo.setUserId(userId);
                cartInfo.setCartPrice(productFeignClient.getSkuPrice(skuId));
                cartInfo.setSkuPrice(productFeignClient.getSkuPrice(skuId));
            }
            //3.3 将数据存入Redis
            //redisTemplate.opsForHash().put(redisKey, hashKey, cartInfo);
            hashOps.put(hashKey, cartInfo);
        }
    }


    /**
     * 获取用户对应hash操作的Key
     *
     * @param userId 用户ID
     * @return
     */
    private String getCartKey(String userId) {
        return RedisConst.USER_KEY_PREFIX + userId + RedisConst.USER_CART_KEY_SUFFIX;
    }


    /**
     * 查询用户购物车列表
     * 版本1：分别查询未登录购物车列表，以及登录的购物车列表-不用
     * 版本2：将两个购物车中商品合并
     *
     * @return
     */
    //@Override
    //public List<CartInfo> cartList(String userId, String userTempId) {
    //    //1.查询未登录购物车列表
    //    List<CartInfo> cartInfoList = null;
    //    //1.1 判断临时用户有值情况下 redis中获取购物车列表
    //    if (StringUtils.isNotBlank(userTempId)) {
    //        //1.2 构建redisKey 创建hash操作对象
    //        String noLogCartKey = getCartKey(userTempId);
    //        BoundHashOperations<String, String, CartInfo> noLoginHashOps = redisTemplate.boundHashOps(noLogCartKey);
    //        cartInfoList = noLoginHashOps.values();
    //    }
    //
    //    //3.已登录的购物车列表
    //    //3.1 判断用户有值情况下 redis中获取购物车列表
    //    if (StringUtils.isNotBlank(userId)) {
    //        //3.2 构建redisKey 创建hash操作对象
    //        String loginCartKey = getCartKey(userId);
    //        BoundHashOperations<String, String, CartInfo> loginHashOps = redisTemplate.boundHashOps(loginCartKey);
    //        cartInfoList = loginHashOps.values();
    //    }
    //
    //    //4.对购物车商品数据进行排序
    //    cartInfoList.sort((o1, o2) -> {
    //        return DateUtil.truncatedCompareTo(o2.getUpdateTime(), o1.getUpdateTime(), Calendar.SECOND);
    //    });
    //    return cartInfoList;
    //}

    /**
     * 查询用户购物车列表
     * 版本2：将两个购物车中商品合并
     * 未登录（没有加购商品，加购商品） 登录（没有加购商品，加购商品）
     * 情况一：（临时用户）用户未登录：加入商品到购物车  用户没登录 返回临时用户加购商品列表
     * 情况二：（临时用户）用户未登录：加入商品到购物车-->用户登录  需要进行合并，删除未登录购物车列表
     *
     * @return
     */
    @Override
    public List<CartInfo> cartList(String userId, String userTempId) {
        //1.（临时用户）用户未登录：加入商品到购物车  用户没登录 返回临时用户加购商品列表
        List<CartInfo> noLoginCartList = null;
        if (StringUtils.isNotBlank(userTempId)) {
            //1.1 构建未登录用户redisKey
            String noLoginCartKey = getCartKey(userTempId);

            //1.2 获取未登录购物车列表
            BoundHashOperations<String, String, CartInfo> noLoginHashOps = redisTemplate.boundHashOps(noLoginCartKey);
            noLoginCartList = noLoginHashOps.values();
        }
        if (StringUtils.isBlank(userId)) {
            noLoginCartList.sort((o1, o2) -> {
                return DateUtil.truncatedCompareTo(o2.getUpdateTime(), o1.getUpdateTime(), Calendar.SECOND);
            });
            return noLoginCartList;
        }

        //2.如果未登录购物车列表中有数据，则需要跟已登录购物车列表进行合并--说明登录了
        //2.1 构建已登录购物车KEY
        String loginCartKey = getCartKey(userId);
        //2.2 构建已登录购物车hash操作对象
        BoundHashOperations<String, String, CartInfo> loginHashOps = redisTemplate.boundHashOps(loginCartKey);

        if (!CollectionUtils.isEmpty(noLoginCartList)) {
            for (CartInfo cartInfo : noLoginCartList) {
                //2.3 判断如果登录购物车中包含商品SKUID 则累加数量  反之则新增
                if (loginHashOps.hasKey(cartInfo.getSkuId().toString())) {
                    CartInfo loginCartInfo = loginHashOps.get(cartInfo.getSkuId().toString());
                    //将离线购物车商品数量跟在线购物车商品数量累加
                    loginCartInfo.setSkuNum(loginCartInfo.getSkuNum() + cartInfo.getSkuNum());
                    //更新登录购物车数据
                    loginHashOps.put(cartInfo.getSkuId().toString(), loginCartInfo);
                } else {
                    //2.4 如果未登录购物车中商品在已登录购物车中不存在新增
                    cartInfo.setUserId(userId);
                    cartInfo.setUpdateTime(new Date());
                    loginHashOps.put(cartInfo.getSkuId().toString(), cartInfo);
                }
            }

            //3. 删除未登录购物车数据
            String noLoginCartKey = getCartKey(userTempId);
            redisTemplate.delete(noLoginCartKey);
        }

        //4.再次查询登录后用户购物车列表
        List<CartInfo> allCartInfoList = loginHashOps.values();
        //4.对购物车商品数据进行排序
        allCartInfoList.sort((o1, o2) -> {
            return DateUtil.truncatedCompareTo(o2.getUpdateTime(), o1.getUpdateTime(), Calendar.SECOND);
        });
        return allCartInfoList;
    }

    /**
     * 变更购物车商品选中状态
     *
     * @param skuId     商品SKUID
     * @param isChecked 状态
     * @return
     */
    @Override
    public void checkCart(String userId, Long skuId, Integer isChecked) {
        //获取用户购物车Key
        String cartKey = getCartKey(userId);
        //获取hash操作对象
        BoundHashOperations<String, String, CartInfo> hashOps = redisTemplate.boundHashOps(cartKey);
        if (hashOps.hasKey(skuId.toString())) {
            //获取商品信息
            CartInfo cartInfo = hashOps.get(skuId.toString());
            //修改状态
            cartInfo.setIsChecked(isChecked);
            //更新购物车商品
            hashOps.put(skuId.toString(), cartInfo);
        }
    }

    /**
     * 删除购物车商品
     * @param userId
     * @param skuId
     */
    @Override
    public void deleteCart(String userId, Long skuId) {
        //获取用户购物车Key
        String cartKey = getCartKey(userId);
        //获取hash操作对象
        BoundHashOperations<String, String, CartInfo> hashOps = redisTemplate.boundHashOps(cartKey);
        //删除购物车商品
        hashOps.delete(skuId.toString());
    }


    /**
     * 查询用户已选中购物车商品列表
     * @param userId
     * @return
     */
    @Override
    public List<CartInfo> getCartCheckedList(Long userId) {
        //1.构建查询购物车Hash结构的Key
        String cartKey = getCartKey(userId.toString());
        //2.查询用户所有的购物车商品
        BoundHashOperations<String, String, CartInfo> hashOps = redisTemplate.boundHashOps(cartKey);
        List<CartInfo> cartInfoList = hashOps.values();
        //3.过滤商品为选中的
        if(!CollectionUtils.isEmpty(cartInfoList)){
            List<CartInfo> cartCheckedList = cartInfoList.stream().filter(cartInfo -> {
                //过滤条件 购物车对象中 isChecked 为1 符合条件
                return cartInfo.getIsChecked() == 1;
            }).collect(Collectors.toList());
            return cartCheckedList;
        }
        return null;
    }


}
